﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Settings;
using com.IronOne.BoardPACWinAppDAO.DbOperations;
using com.IronOne.BoardPACWinAppDAO.DB;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Util;

namespace com.IronOne.BoardPACWinAppDAO.Init
{
    public class InitDAO : IInitDAO
    {
        private readonly IDbOperations _dbOperations;

        public InitDAO()
        {
            _dbOperations = new DbOperations.DbOperations();
        }

        public async Task<AppSettingModel> SelectAllAppSettings()
        {
            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var data = await conn.Table<AppSettings>().ToListAsync();
                var modelData = EntityToModelMapper.MapAppSettingsToAppSettingModel(data);
                return modelData;
            }
            catch (Exception)
            {
                return null;
            }
        }

        public async Task<bool> InsertAppSettingsAsync(AppSettingModel asmData)
        {
            try
            {
                var count = await InsertorUpdate(asmData);
                return count > 0;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async Task<bool> InsertDateFormatsNSyncFreqsAsync(AppSettingModel asmData)
        {
            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var insertAppSettingsList = new List<AppSettings>();
                var updateAppSettingsList = new List<AppSettings>();

                #region DateFormats | DateFormatSelected

                // @: will break each date format key-value pairs
                // #: will break key and the value of the key-value pair
                var dateFormats = "";
                for (var i = 0; i < asmData.DateFormats.Count; i++)
                {
                    if (i == asmData.DateFormats.Count - 1)
                    {
                        dateFormats = dateFormats + asmData.DateFormats[i].Key + "#" + asmData.DateFormats[i].Value;
                        break;
                    }
                    dateFormats = dateFormats + asmData.DateFormats[i].Key + "#" + asmData.DateFormats[i].Value + "@";
                }
                var appSett = await
                    conn.Table<AppSettings>().Where(x => x.SettingName.Equals("DateFormats")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings {SettingName = "DateFormats", SettingValue = dateFormats});
                else
                {
                    appSett.SettingValue = dateFormats;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region SyncFrequencies | SyncFrequencySelected

                // @: will break each date format key-value pairs
                // #: will break key and the value of the key-value pair
                var syncFrequencies = "";
                for (var i = 0; i < asmData.SyncFrequencies.Count; i++)
                {
                    if (i == asmData.SyncFrequencies.Count - 1)
                    {
                        syncFrequencies = syncFrequencies + asmData.SyncFrequencies[i].Key + "#" +
                                          asmData.SyncFrequencies[i].Value;
                        break;
                    }
                    syncFrequencies = syncFrequencies + asmData.SyncFrequencies[i].Key + "#" +
                                      asmData.SyncFrequencies[i].Value + "@";
                }
                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("SyncFrequencies"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SyncFrequencies",
                        SettingValue = syncFrequencies
                    });
                else
                {
                    appSett.SettingValue = syncFrequencies;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region MinWebVersion

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("MinWebVersion"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "MinWebVersion",
                        SettingValue = asmData.MinWebVersion
                    });
                else
                {
                    appSett.SettingValue = asmData.MinWebVersion;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                var count = 0;
                if (insertAppSettingsList.Count > 0)
                {
                    count = await conn.InsertAllAsync(insertAppSettingsList);
                }
                if (updateAppSettingsList.Count > 0)
                {
                    count = count + await conn.UpdateAllAsync(updateAppSettingsList);
                }

                return count > 0;
            }
            catch (Exception)
            {
                throw;
            }
        }

        //TODO: this should migrated to user database
        public async Task<string> GetDateFormat()
        {
            #region DateFormat

            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(
                                x => x.SettingName.Equals(ApplicationConstants.GeneralDbSettingNames.DateFormatSelected))
                            .FirstOrDefaultAsync();
                var val = appSett.SettingValue.Split('#')[0];
                if (val.Equals("-1"))
                    return "dd-MMM-yyyy";

                return val;
            }
            catch (Exception)
            {
                throw;
            }

            #endregion
        }

        /// <summary>
        ///     Get server time and parse it using Utility.GetDate
        /// </summary>
        /// <returns></returns>
        public async Task<DateTime> GetDateTimeFromDb()
        {
            #region DateTime

            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var appSett =
                    await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerTime")).FirstOrDefaultAsync();
                return Utility.GetDate(appSett.SettingValue);
            }
            catch (Exception)
            {
                throw;
            }

            #endregion
        }

        public async Task<ResponseDataModel> SyncTranckingInfoToGeneralDb(ResponseDataModel responseModel2)
        {
            var rdm = new ResponseDataModel();
            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var insertAppSettingsList = new List<AppSettings>();
                var updateAppSettingsList = new List<AppSettings>();

                #region ServerId

                var appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerId")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ServerId",
                        SettingValue = responseModel2.ServerId.ToString()
                    });
                else
                {
                    appSett.SettingValue = responseModel2.ServerId.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region ServerTime

                appSett =
                    await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerTime")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ServerTime",
                        SettingValue = responseModel2.ServerTime.ToString()
                    });
                else
                {
                    appSett.SettingValue = responseModel2.ServerTime.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region WebAppVersion

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("WebAppVersion"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "WebAppVersion",
                        SettingValue = responseModel2.WebAppVersion
                    });
                else
                {
                    appSett.SettingValue = responseModel2.WebAppVersion;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region CooperateId

                appSett =
                    await
                        conn.Table<AppSettings>().Where(x => x.SettingName.Equals("CooperateId")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "CooperateId",
                        SettingValue = responseModel2.CooperateId.ToString()
                    });
                else
                {
                    appSett.SettingValue = responseModel2.CooperateId.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                if (insertAppSettingsList.Count > 0)
                {
                    await conn.InsertAllAsync(insertAppSettingsList);
                }
                if (updateAppSettingsList.Count > 0)
                {
                    await conn.UpdateAllAsync(updateAppSettingsList);
                }
                return rdm;
            }
            catch (Exception)
            {
                throw;
            }
        }

        private async Task<int> InsertorUpdate(AppSettingModel asmData)
        {
            try
            {
                var conn = _dbOperations.GetAsyncConnection(DbConnectionType.GeneralDbConnection);

                var insertAppSettingsList = new List<AppSettings>();
                var updateAppSettingsList = new List<AppSettings>();

                #region AppOfflineUsageCheck (Commented)

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("AppOfflineUsageCheck")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "AppOfflineUsageCheck", SettingValue = asmData.AppOfflineUsageCheck.ToString() });
                else
                {
                    appSett.SettingValue = asmData.AppOfflineUsageCheck.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region MinWebVersion

                var appSett = await
                    conn.Table<AppSettings>()
                        .Where(x => x.SettingName.Equals("MinWebVersion"))
                        .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "MinWebVersion",
                        SettingValue = asmData.MinWebVersion
                    });
                else
                {
                    appSett.SettingValue = asmData.MinWebVersion;
                    if (!String.IsNullOrWhiteSpace(asmData.MinWebVersion))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region CooperateId (Commented and moved to SyncTranckingInfoToGeneralDb())

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("CooperateId")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "CooperateId", SettingValue = asmData.CooperateId.ToString() });
                else
                {
                    appSett.SettingValue = asmData.CooperateId.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region DateFormats | DateFormatSelected

                // @: will break each date format key-value pairs
                // #: will break key and the value of the key-value pair
                var dateFormats = "";
                for (var i = 0; i < asmData.DateFormats.Count; i++)
                {
                    if (i == asmData.DateFormats.Count - 1)
                    {
                        dateFormats = dateFormats + asmData.DateFormats[i].Key + "#" + asmData.DateFormats[i].Value;
                        break;
                    }
                    dateFormats = dateFormats + asmData.DateFormats[i].Key + "#" + asmData.DateFormats[i].Value + "@";
                }
                appSett =
                    await
                        conn.Table<AppSettings>().Where(x => x.SettingName.Equals("DateFormats")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings {SettingName = "DateFormats", SettingValue = dateFormats});
                else
                {
                    appSett.SettingValue = dateFormats;
                    updateAppSettingsList.Add(appSett);
                }

                //Key = date format  | Value = date format example
                var dfSelected = asmData.DateFormatSelected.Key + "#" + asmData.DateFormatSelected.Value;
                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("DateFormatSelected"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "DateFormatSelected",
                        SettingValue = dfSelected
                    });
                else
                {
                    appSett.SettingValue = dfSelected;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region DownloadUrl

                appSett =
                    await
                        conn.Table<AppSettings>().Where(x => x.SettingName.Equals("DownloadUrl")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "DownloadUrl",
                        SettingValue = asmData.DownloadUrl
                    });
                else
                {
                    appSett.SettingValue = asmData.DownloadUrl;
                    if (!String.IsNullOrWhiteSpace(asmData.DownloadUrl))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region Emails

                var emails = "";
                if (asmData.SupportInfoEmails != null)
                {
                    for (var i = 0; i < asmData.SupportInfoEmails.Length; i++)
                    {
                        if (i == asmData.SupportInfoEmails.Length - 1)
                        {
                            emails = emails + asmData.SupportInfoEmails[i];
                            break;
                        }
                        emails = emails + asmData.SupportInfoEmails[i] + ",";
                    }
                }
                //appSettList.Add(new AppSettings { SettingName = "Emails", SettingValue = emails });
                appSett =
                    await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("Emails")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings {SettingName = "Emails", SettingValue = emails});
                else
                {
                    appSett.SettingValue = emails;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region EnforceOnlineLoginDuration (Commented)

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("EnforceOnlineLoginDuration")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "EnforceOnlineLoginDuration", SettingValue = asmData.EnforceOnlineLoginDuration.ToString() });
                else
                {
                    appSett.SettingValue = asmData.EnforceOnlineLoginDuration.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region MaxOfflineLoginInterval (Commented)

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("MaxOfflineLoginInterval")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "MaxOfflineLoginInterval", SettingValue = asmData.MaxOfflineLoginInterval.ToString() });
                else
                {
                    appSett.SettingValue = asmData.MaxOfflineLoginInterval.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region OfflineConsecutiveLimit (Commented)

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("OfflineConsecutiveLimit")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "OfflineConsecutiveLimit", SettingValue = asmData.OfflineConsecutiveLimit.ToString() });
                else
                {
                    appSett.SettingValue = asmData.OfflineConsecutiveLimit.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region SupportInfoPhone

                var phones = "";
                if (asmData.SupportInfoPhones != null)
                {
                    for (var i = 0; i < asmData.SupportInfoPhones.Length; i++)
                    {
                        if (i == asmData.SupportInfoPhones.Length - 1)
                        {
                            phones = phones + asmData.SupportInfoPhones[i];
                            break;
                        }
                        phones = phones + asmData.SupportInfoPhones[i] + ",";
                    }
                }
                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("SupportInfoPhone"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings {SettingName = "SupportInfoPhone", SettingValue = phones});
                else
                {
                    appSett.SettingValue = phones;
                    if (!String.IsNullOrWhiteSpace(phones))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region ServerCommands

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("ServerCommands"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ServerCommands",
                        SettingValue = asmData.ServerCommands
                    });
                else
                {
                    appSett.SettingValue = asmData.ServerCommands;
                    if (!String.IsNullOrWhiteSpace(asmData.ServerCommands))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region ServerId (Commented and moved to SyncTranckingInfoToGeneralDb())

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerId")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "ServerId", SettingValue = asmData.ServerId.ToString() });
                else
                {
                    appSett.SettingValue = asmData.ServerId.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region ServerTime (Commented and moved to SyncTranckingInfoToGeneralDb())

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerTime")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "ServerTime", SettingValue = asmData.ServerTime.ToString() });
                else
                {
                    appSett.SettingValue = asmData.ServerTime.ToString();
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                #region ServerMessage

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("ServerMessage"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ServerMessage",
                        SettingValue = asmData.ServerMessage
                    });
                else
                {
                    appSett.SettingValue = asmData.ServerMessage;
                    if (!String.IsNullOrWhiteSpace(asmData.ServerMessage))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region ServerUrl

                appSett =
                    await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("ServerUrl")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ServerUrl",
                        SettingValue = asmData.ServerUrl
                    });
                else
                {
                    appSett.SettingValue = asmData.ServerUrl;
                    if (!String.IsNullOrWhiteSpace(asmData.ServerUrl))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region ShowSupportInfo

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("ShowSupportInfo"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "ShowSupportInfo",
                        SettingValue = asmData.ShowSupportInfo.ToString()
                    });
                else
                {
                    appSett.SettingValue = asmData.ShowSupportInfo.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region SupportName

                appSett =
                    await
                        conn.Table<AppSettings>().Where(x => x.SettingName.Equals("SupportName")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SupportName",
                        SettingValue = asmData.SupportInfoName
                    });
                else
                {
                    appSett.SettingValue = asmData.SupportInfoName;
                    if (!String.IsNullOrWhiteSpace(asmData.SupportInfoName))
                        updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region SyncFrequencies | SyncFrequencySelected

                // @: will break each date format key-value pairs
                // #: will break key and the value of the key-value pair
                var syncFrequencies = "";
                for (var i = 0; i < asmData.SyncFrequencies.Count; i++)
                {
                    if (i == asmData.SyncFrequencies.Count - 1)
                    {
                        syncFrequencies = syncFrequencies + asmData.SyncFrequencies[i].Key + "#" +
                                          asmData.SyncFrequencies[i].Value;
                        break;
                    }
                    syncFrequencies = syncFrequencies + asmData.SyncFrequencies[i].Key + "#" +
                                      asmData.SyncFrequencies[i].Value + "@";
                }
                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("SyncFrequencies"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SyncFrequencies",
                        SettingValue = syncFrequencies
                    });
                else
                {
                    appSett.SettingValue = syncFrequencies;
                    updateAppSettingsList.Add(appSett);
                }

                //Key = date format  | Value = date format example
                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("SyncFrequencySelected"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SyncFrequencySelected",
                        SettingValue = asmData.SyncFrequencySelected.Key
                    });
                else
                {
                    appSett.SettingValue = asmData.SyncFrequencySelected.Key;
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region SyncFrequencyServerDecides

                appSett =
                    await
                        conn.Table<AppSettings>()
                            .Where(x => x.SettingName.Equals("SyncFrequencyServerDecides"))
                            .FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SyncFrequencyServerDecides",
                        SettingValue = asmData.SyncFrequencyServerDecides.ToString()
                    });
                else
                {
                    appSett.SettingValue = asmData.SyncFrequencyServerDecides.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region SyncSettings

                appSett =
                    await
                        conn.Table<AppSettings>().Where(x => x.SettingName.Equals("SyncSettings")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings
                    {
                        SettingName = "SyncSettings",
                        SettingValue = asmData.SyncSettings.ToString()
                    });
                else
                {
                    appSett.SettingValue = asmData.SyncSettings.ToString();
                    updateAppSettingsList.Add(appSett);
                }

                #endregion

                #region WebAppVersion (Commented and moved to SyncTranckingInfoToGeneralDb())

                /*appSett = await conn.Table<AppSettings>().Where(x => x.SettingName.Equals("WebAppVersion")).FirstOrDefaultAsync();
                if (appSett == null)
                    insertAppSettingsList.Add(new AppSettings { SettingName = "WebAppVersion", SettingValue = asmData.WebAppVersion });
                else
                {
                    appSett.SettingValue = asmData.WebAppVersion;
                    updateAppSettingsList.Add(appSett);
                }*/

                #endregion

                var count = 0;
                if (insertAppSettingsList.Count > 0)
                {
                    count = await conn.InsertAllAsync(insertAppSettingsList);
                }
                if (updateAppSettingsList.Count > 0)
                {
                    count = count + await conn.UpdateAllAsync(updateAppSettingsList);
                }
                return count;
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}